const path = require('path')
const fs = require('fs')
const compressing = require('compressing')
// readline 实例
const readline = require('readline').createInterface({
    input: process.stdin,
    output: process.stdout
  })

// 判断文件类型，注意包含文件夹类型
const fileTypes = ['jpg','png','jpeg','webp']
// 解压类型
const unzipTypes = ['zip','tar','tgz','gzip']
const args = process.argv
// 用户输入的目录路径
let filePath;
// 文件输出目录路径
let savePath;
// 文件命名计数
let count = 0;


exec()

// console.log("路径参数",args)
// 由于路径中如果存在空格，回解析为多个参数，因此默认为只有一个参数args[2],如果args[2]后续还有则认为是路径参数对其进行合并
// filePath = path.resolve(args[2]);
// if(args.length > 3) {
// 	for(let i = 3; i < args.length;i++) {
// 		filePath += ` ${args[i]}`;
// 	}
// }
function exec() {
    readline.question('path: ', targetPath => {
    savePath = path.join(targetPath,'images');
    console.log("Path:",targetPath)
    console.log("savePath:",savePath)

    // 对目标目录解压
    readdirAndUncompress(targetPath)
        .then(() => {
            dirTravelingAndRename(targetPath)     // 遍历文件夹并重命名
            console.log("\nDone ! ------------------------------------------\n",'输出路径:','',savePath);
            console.log('\n');
            readline.question('是否需要继续处理(Y/N)：', select => {
               switch(select) {
                  case 'Y':
                  case 'y':
                      exec()
                      break
                  case 'N':
                  case 'n':
                      // 需要关闭，否则会一直等待输入
                      readline.close()
                      break
                  default:
                      readline.close()
               }
            })

        })    
        .catch(error => console.warn(error))
    
})

}

/**
遍历解压目标目录内的压缩文件
@param targetPath 需要解压的目标路径
**/

function readdirAndUncompress(targetPath) {
    return new Promise((resolve,reject) => {
        try {
            let files = []
            // withFileTypes: true 返回<fs.Dirent> 对象数组
            fs.readdirSync(targetPath,{withFileTypes: true}).forEach((item) => {
                // 判断文件类型是否符合
                const ext = item.name.split('.')[1]
                if(!item.isFile() || unzipTypes.indexOf(ext) === -1) return
                files.push(item)
            })

            // 创建输出目录 recursive 指示是否应创建父文件夹
            fs.mkdirSync(savePath,{recursive: true})
            
            let counter = 0
            //遍历读取到的文件列表
            files.forEach(({name:filename}) => {
                // 判断文件类型是否符合
                const ext = filename.split('.')[1]
    
                // 获取当前文件的完整路径
                const filePath = path.join(targetPath, filename);
                // 解压后文件的输出路径
                const outputDir = path.join(targetPath,filename.split('.')[0])
               
                // 解压zip  
                compressing[ext].uncompress(filePath, outputDir).then(() => {
                    
                    counter++;
                    process.stdout.write(`解压进度：${counter} / ${files.length} \r`)
                    if(counter === files.length){
                        resolve()
                    }
                })
            });
        } catch (error) {
            reject(error)
        }
    })

}


/**
文件夹遍历
@param targetPath 需要遍历的目标路径
**/

function dirTravelingAndRename(targetPath) {
    try {

        let dirs = []
        // withFileTypes: true 返回<fs.Dirent> 对象数组
        fs.readdirSync(targetPath,{withFileTypes: true}).forEach((item) => {
            if(!item.isDirectory() || item.name === 'images') return
            dirs.push(item)
        })
        

        const sortDirs = dirs.sort((a, b) => {
             // 提取每个字符串中的第一个数字（即起始话数）
                const numA = parseInt(a.name.match(/\d+/)[0], 10);
                const numB = parseInt(b.name.match(/\d+/)[0], 10);

                // 比较数字大小
                return numA - numB;
        });

        console.log("\n文件夹排序:",sortDirs);

        //遍历读取到的文件夹列表
        sortDirs.forEach(({name:dirname}) => {

            // 获取当前文件夹的绝对路径
            const dirPath = path.join(targetPath, dirname);
            fs.readdirSync(dirPath ,{withFileTypes: true}).forEach((item) => {
                const {name} = item
                // 文件扩展名
                const ext = name.split('.')[1]
                // 判断为文件 并且 符合允许的文件扩展名
                if(!item.isFile() && fileTypes.indexOf(ext) !== -1 ) return
  
                // 获取当前文件的完整路径
                const filePath = path.join(dirPath, name);

                rename(filePath,savePath,ext)

            })
        });

        // 删除空文件夹
        sortDirs.forEach(({name})=> {
            // 获取当前文件夹的完整路径
            const dirPath = path.join(targetPath,name );
            fs.rmdirSync(dirPath)
        })
    } catch (error) {
        console.warn(error)
    }
}



/**
 * 文件重命名
 * @param {*} oldFilePath  旧文件完整路径包含文件名 
 * @param {*} newPath      新文件输出目录路径
 * @param {*} newName      重命名名称
 * @param {string} ext     文件扩展名
 */
function rename (oldFilePath, newPath,ext) {
    count++;
    // 文件名前补 '0'
    const newName = `${String(count).padStart(5,'0')}.${ext}`
    // 新目录/文件的完整路径及名；如果新路径与原路径相同，而只文件名不同，则是重命名
    const newFilePath = path.join(newPath,newName)
    try {
        // 为了保证文件顺序
        fs.renameSync(oldFilePath, newFilePath)
        // console.log('重命名成功',oldFilePath,'---->',newName);
        process.stdout.write(`重命名文件：${count} \r`)
    } catch (error) {
        console.error(error);
    }
}